﻿using System;
using UnityEditor;
using UnityEngine;

namespace Miao.Editor
{
    /// <summary>
    /// 编辑器GUI工具
    /// </summary>
    public static class EditorGUITool
    {
        /// <summary>
        /// 在1920x1080分辨率下的字符像素宽度
        /// </summary>
        public static float charWidth = 12.4f;

        /// <summary>
        /// 自适应常量
        /// </summary>
        public const int audo = -1;

        private static readonly GUILayoutOption minWidth = GUILayout.MinWidth(0f);

        public static Rect BeginVertical()
        {
            return EditorGUILayout.BeginVertical();
        }
        public static Rect BeginVertical(GUIStyle guiStyle)
        {
            return EditorGUILayout.BeginVertical(guiStyle);
        }
        public static Rect BeginVertical(params GUILayoutOption[] options)
        {
            return EditorGUILayout.BeginVertical(options);
        }
        public static void BeginDisabledGroup(bool disable)
        {
            EditorGUI.BeginDisabledGroup(disable);
        }
        public static Rect BeginHorizontal()
        {
            return EditorGUILayout.BeginHorizontal();
        }
        public static Rect BeginHorizontal(GUIStyle guiStyle)
        {
            return EditorGUILayout.BeginHorizontal(guiStyle);
        }
        public static Rect BeginHorizontal(params GUILayoutOption[] options)
        {
            return EditorGUILayout.BeginHorizontal(options);
        }
        public static void EndVertical()
        {
            EditorGUILayout.EndVertical();
        }
        public static void EndHorizontal()
        {
            EditorGUILayout.EndHorizontal();
        }
        public static void EndDisabledGroup()
        {
            EditorGUI.EndDisabledGroup();
        }
        public static void Space()
        {
            EditorGUILayout.Space();
        }
        public static void Space(float width)
        {
            EditorGUILayout.Space(width);
        }
        public static void FlexibleSpace()
        {
            GUILayout.FlexibleSpace();
        }
        public static void ExitGUI()
        {
            UnityEngine.GUIUtility.ExitGUI();
        }

        public static Rect GetRect(float width, float height)
        {
            return GUILayoutUtility.GetRect(width, height);
        }
        public static void DrawRect(Rect rect, Color color)
        {
            EditorGUI.DrawRect(rect, color);
        }
        public static void LabelField(string name)
        {
            LabelField(name, name.Length);
        }
        public static void LabelField(string name, GUIStyle style)
        {
            LabelField(name, name.Length, style);
        }
        public static void LabelField(string name, int nameLength)
        {
            EditorGUILayout.LabelField(name, GetStringWidthOption(nameLength), minWidth);
        }
        public static void LabelField(string name, int nameLength, GUIStyle style)
        {
            EditorGUILayout.LabelField(name, style, GetStringWidthOption(nameLength));
        }
        public static int PopupField(int curentIndex, string[] popup)
        {
            return EditorGUILayout.Popup(curentIndex, popup);
        }
        public static int PopupField(string name, int curentIndex, string[] popup)
        {
            return PopupField(name, curentIndex, popup, name.Length);
        }
        public static int PopupField(string name, int curentIndex, string[] popup, int nameLength)
        {
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField(name, GetStringWidthOption(nameLength));
            int newIndex = EditorGUILayout.Popup(curentIndex, popup);
            EditorGUILayout.EndHorizontal();
            return newIndex;
        }
        public static T EnumField<T>(string name, T value) where T : Enum
        {
            return EnumField(name, value, name.Length);
        }
        public static T EnumField<T>(string name, T value, int nameLength) where T : Enum
        {
            float preWidth = EditorGUIUtility.labelWidth;
            EditorGUIUtility.labelWidth = charWidth * nameLength;
            T newValue = (T)EditorGUILayout.EnumPopup(name, value);
            EditorGUIUtility.labelWidth = preWidth;
            return newValue;
        }
        public static T EnumField<T>(string name, T value, string[] display, int nameLength) where T : Enum
        {
            float preWidth = EditorGUIUtility.labelWidth;
            EditorGUIUtility.labelWidth = charWidth * nameLength;
            int newValue = EditorGUILayout.Popup(name, Convert.ToInt32(value), display);
            EditorGUIUtility.labelWidth = preWidth;
            return (T)Enum.ToObject(typeof(T), newValue);
        }
        public static T ObjectField<T>(T obj) where T : UnityEngine.Object
        {
            return EditorGUILayout.ObjectField(obj, typeof(T), true) as T;
        }
        public static T ObjectField<T>(T obj, bool allowSceneObjects) where T : UnityEngine.Object
        {
            return EditorGUILayout.ObjectField(obj, typeof(T), allowSceneObjects) as T;
        }
        public static T ObjectField<T>(string name, T obj) where T : UnityEngine.Object
        {
            return ObjectField(name, obj, true, name.Length);
        }
        public static T ObjectField<T>(string name, T obj, int nameLength) where T : UnityEngine.Object
        {
            return ObjectField(name, obj, true, nameLength);
        }
        public static T ObjectField<T>(string name, T obj, bool allowSceneObjects) where T : UnityEngine.Object
        {
            return ObjectField(name, obj, allowSceneObjects, name.Length);
        }
        public static T ObjectField<T>(string name, T obj, bool allowSceneObjects, int nameLength) where T : UnityEngine.Object
        {
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField(name, GetStringWidthOption(nameLength));
            T result = EditorGUILayout.ObjectField(obj, typeof(T), allowSceneObjects) as T;
            EditorGUILayout.EndHorizontal();
            return result;
        }
        public static int IntField(string name, int value)
        {
            return IntField(name, value, name.Length);
        }
        public static int IntField(string name, int value, int nameLength)
        {
            float preWidth = EditorGUIUtility.labelWidth;
            EditorGUIUtility.labelWidth = charWidth * nameLength;
            int newValue = EditorGUILayout.IntField(name, value);
            EditorGUIUtility.labelWidth = preWidth;
            return newValue;
        }
        public static float FloatField(string name, float value)
        {
            return FloatField(name, value, name.Length);
        }
        public static float FloatField(string name, float value, int nameLength)
        {
            float preWidth = EditorGUIUtility.labelWidth;
            EditorGUIUtility.labelWidth = charWidth * nameLength;
            float newValue = EditorGUILayout.FloatField(name, value);
            EditorGUIUtility.labelWidth = preWidth;
            return newValue;
        }
        public static bool BoolField(string name, bool value)
        {
            return BoolField(name, value, name.Length);
        }
        public static bool BoolField(string name, bool value, int nameLength)
        {
            float preWidth = EditorGUIUtility.labelWidth;
            EditorGUIUtility.labelWidth = charWidth * nameLength;
            bool newValue = EditorGUILayout.Toggle(name, value);
            EditorGUIUtility.labelWidth = preWidth;
            return newValue;
            //EditorGUILayout.BeginHorizontal(GUILayout.MinWidth(1f));//必须加上 GUILayout.MinWidth(1f), 否则 Toggle宽度会错误, 这是Unity的一个小问题
            //EditorGUILayout.LabelField(name, GetStringWidthOption(nameLength));
            //bool newValue = EditorGUILayout.Toggle(value, GUILayout.Width(14f));
            //EditorGUILayout.EndHorizontal();
            //return newValue;
        }
        public static string StringField(string text)
        {
            return EditorGUILayout.TextField(text);
        }
        public static string StringField(string name, string text)
        {
            return StringField(name, text, name.Length);
        }
        public static string StringField(string name, string text, int nameLength)
        {
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField(name, GetStringWidthOption(nameLength));
            string newText = EditorGUILayout.TextField(text);
            EditorGUILayout.EndHorizontal();
            return newText;
        }
        public static int SliderInt(int value, int minValue, int maxValue)
        {
            return EditorGUILayout.IntSlider(value, minValue, maxValue);
        }
        public static int SliderInt(string name, int value, int minValue, int maxValue)
        {
            return SliderInt(name, value, minValue, maxValue, name.Length);
        }
        public static int SliderInt(string name, int value, int minValue, int maxValue, int nameLength)
        {
            EditorGUILayout.BeginHorizontal();
            float preWidth = EditorGUIUtility.labelWidth;
            EditorGUIUtility.labelWidth = charWidth * nameLength;
            int newValue = (int)EditorGUILayout.Slider(name, value, minValue, maxValue);
            EditorGUIUtility.labelWidth = preWidth;
            EditorGUILayout.EndHorizontal();
            return newValue;
        }
        public static float Slider(float value, float minValue, float maxValue)
        {
            return EditorGUILayout.Slider(value, minValue, maxValue);
        }
        public static float Slider(string name, float value, float minValue, float maxValue)
        {
            return Slider(name, value, minValue, maxValue, name.Length);
        }
        public static float Slider(string name, float value, float minValue, float maxValue, int nameLength)
        {
            float preWidth = EditorGUIUtility.labelWidth;
            EditorGUIUtility.labelWidth = charWidth * nameLength;
            float newValue = EditorGUILayout.Slider(name, value, minValue, maxValue);
            EditorGUIUtility.labelWidth = preWidth;
            return newValue;
        }
        public static bool Button(string name)
        {
            return GUILayout.Button(name);
        }
        public static bool Button(string name, int nameLength)
        {
            return GUILayout.Button(name, GetStringWidthOption(nameLength + 1));//加1个字符宽度, 否则Button显示不全
        }
        public static bool Button(string name, params GUILayoutOption[] options)
        {
            return GUILayout.Button(name, options);
        }
        public static bool Button(string name, float width = audo, float height = audo)
        {
            if (width == audo)
            {
                if (height == audo) return GUILayout.Button(name);
                return GUILayout.Button(name, GUILayout.Height(height));
            }
            else
            {
                if (height == audo) return GUILayout.Button(name, GUILayout.Width(width));
                return GUILayout.Button(name, GUILayout.Width(width), GUILayout.Height(height));
            }
        }

        /// <summary>
        /// 获取字符串在屏幕上的像素宽度
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static float GetStringWidth(string str)
        {
            return str.Length * charWidth;
        }
        /// <summary>
        /// 获取长度为 <paramref name="stringLength"/> 的字符串像素宽度的 <see cref="GUILayoutOption"/>
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static GUILayoutOption GetStringWidthOption(int stringLength)
        {
            return GUILayout.Width(stringLength * charWidth);
        }
        /// <summary>
        /// 获取字符串 <paramref name="str"/> 像素宽度的 <see cref="GUILayoutOption"/>
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static GUILayoutOption GetStringWidthOption(string str)
        {
            return GUILayout.Width(str.Length * charWidth);
        }
        /// <summary>
        /// 获取字符串最小像素宽度的 <see cref="GUILayoutOption"/>
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static GUILayoutOption GetStringMinWidthOption(string str)
        {
            return GUILayout.MinWidth(str.Length * charWidth);
        }
        /// <summary>
        /// 获取字符串最小像素宽度的 <see cref="GUILayoutOption"/>
        /// </summary>
        /// <returns></returns>
        public static GUILayoutOption GetStringMinWidthOption(int stringLength)
        {
            return GUILayout.MinWidth(stringLength * charWidth);
        }
        /// <summary>
        /// 获取字符串最大像素宽度的 <see cref="GUILayoutOption"/>
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static GUILayoutOption GetStringMaxWidthOption(string str)
        {
            return GUILayout.MaxHeight(str.Length * charWidth);
        }
        /// <summary>
        /// 获取字符串最大像素宽度的 <see cref="GUILayoutOption"/>
        /// </summary>
        /// <param name="stringLength"></param>
        /// <returns></returns>
        public static GUILayoutOption GetStringMaxWidthOption(int stringLength)
        {
            return GUILayout.MaxHeight(stringLength * charWidth);
        }
    }
}